home *** CD-ROM | disk | FTP | other *** search
- /*
- File: SampleDriver.c
-
- Contains: Sample code for a PCI device driver that supports PCI power off.
-
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
-
- Version: 1.0
-
- Copyright: © 1999 by Apple Computer, Inc., all rights reserved.
-
- File Ownership:
-
- DRI: xxx put dri here xxx
-
- Other Contact: xxx put other contact here xxx
-
- Technology: xxx put technology here xxx
-
- Writers:
-
- (SAJ) Scott Johnson
- (BB) Bob Bradley
-
- Change History (most recent first):
-
- <1> 11/30/99 SAJ Updated with more detailed comments and new selectors.
- <0+> 7/11/99 BB First checked in.
- */
-
- #include <Devices.h>
- #include <DriverFamilyMatching.h>
- #include <Power.h>
-
- #include "SampleDriver.h"
-
- /*==================================================================================================
- TheDriverDescription
- ==================================================================================================*/
-
- DriverDescription TheDriverDescription =
- {
- kTheDescriptionSignature, // driverDescSignature
- kInitialDriverDescriptor, // driverDescVersion
-
- { // MacDriverType
- "\psample-hardware", // nameInfoStr
- { // NumVersion
- kDriverMajorVersion, // majorRev
- kDriverMinorAndBugFixVersion, // minorAndBugRev
- kDriverVersionStage, // stage
- kDriverNonReleaseVersion // nonRelRev
- }
- },
- { // DriverOSRuntime
- 0, // driverRuntime
-
- "\pSample Driver", // driverName
- 0, 0, 0, 0, 0, 0, 0, 0, // driverDescReserved
- },
- { // DriverOSService
- 1, // nServices
- { // DriverOSService
- kServiceCategoryGeneric, // serviceCategory
- kNdrvTypeIsGeneric, // serviceType
- { 0x1, 0x01, developStage, 0x1 } // version
- }
- }
- };
-
- /*==================================================================================================
- Macros
- ==================================================================================================*/
-
- #define HasPowerHandlerSupport() \
- ( ( ( Ptr ) AddDevicePowerHandler ) != ( ( Ptr ) kUnresolvedCFragSymbolAddress ) )
-
- /*==================================================================================================
- Global
- ==================================================================================================*/
-
- RegEntryID gOurDeviceRegEntry;
-
- /*==================================================================================================
- DoDriverIO
- ==================================================================================================*/
-
- OSErr DoDriverIO( AddressSpaceID spaceID,
- IOCommandID commandID,
- IOCommandContents contents,
- IOCommandCode code,
- IOCommandKind kind )
- {
- #pragma unused( spaceID, commandID, kind )
-
- OSStatus err;
-
- err = noErr;
- switch( code )
- {
- case kOpenCommand:
- break;
-
- case kReadCommand:
- break;
-
- case kWriteCommand:
- break;
-
- case kControlCommand:
- break;
-
- case kStatusCommand:
- break;
-
- case kKillIOCommand:
- break;
-
- case kInitializeCommand:
- if( HasPowerHandlerSupport() )
- {
- err = RegistryEntryIDCopy (&contents.initialInfo->deviceEntry, &gOurDeviceRegEntry);
- if ( err == noErr )
- err = AddDevicePowerHandler( &gOurDeviceRegEntry,
- SampleDriverPowerHandler,
- 0,
- NULL );
- }
- break;
-
- case kFinalizeCommand:
- if( HasPowerHandlerSupport() )
- {
- ( void ) RemoveDevicePowerHandler( &contents.initialInfo->deviceEntry );
- }
- break;
-
- case kReplaceCommand:
- if( HasPowerHandlerSupport() )
- {
- err = RegistryEntryIDCopy (&contents.initialInfo->deviceEntry, &gOurDeviceRegEntry);
- if ( err == noErr )
- err = AddDevicePowerHandler( &gOurDeviceRegEntry,
- SampleDriverPowerHandler,
- 0,
- NULL );
- }
- break;
-
- case kSupersededCommand:
- if( HasPowerHandlerSupport() )
- {
- ( void ) RemoveDevicePowerHandler( &contents.initialInfo->deviceEntry );
- }
- break;
-
- case kSuspendCommand:
- break;
-
- case kResumeCommand:
- break;
-
- default:
- break;
- }
- return( err );
- }
-
- /*==================================================================================================
- SampleDriverPowerHandler
- ==================================================================================================*/
-
- pascal OSStatus SampleDriverPowerHandler( UInt32 inMessage,
- void * ioParam,
- UInt32 inRefCon,
- RegEntryID * inRegID )
- {
- #pragma unused( inRefCon, inRegID )
-
- OSStatus err;
-
- // Always return kPowerMgtMessageNotHandled for messages we don't respond to.
- err = kPowerMgtMessageNotHandled;
-
- switch( inMessage )
- {
- case kSleepRequest:
- // Complete pending I/O during kSleepRequest, but don't suspend
- // further I/O requests until kSleepDemand.
- // CPU interrupts are still enabled!
- err = CanWeSleepDeviceNow();
- break;
-
-
- case kSleepDemand:
- // Now it is okay to suspend further I/O. Do complete any pending
- // I/O and then turn off device interrupts and save device-specific
- // registers and PCI config space (beyond the base 64 bytes which
- // Apple SSW saves), as well as any other volatile memory for the
- // device.
- // CPU interrupts are NOT enabled!
- PutOurDeviceToSleep();
- err = noErr;
- break;
-
-
- case kWakeToDoze:
- // IMPORTANT!
- // The kWakeToDoze message is sent on a partial wake. Most devices won't do anything
- // different than when they receive a kSleepWakeUp message. However, they MUST at least
- // do that if they don't support partial wakeup. The message cannot simply be ignored.
- case kSleepWakeUp:
- // CPU interrupts are NOT enabled!
- WakeOurDevice();
- err = noErr;
- break;
-
-
- case kDozeToFullWakeUp:
- // This message only needs to do anything interesting if the device supports
- // partial wakeup (and handled kWakeToDoze differently than a normal kSleepWakeUp).
- break;
-
-
- case kSleepRevoke:
- // Reverse any steps taken during kSleepRequest handling so that we may resume
- // full functionality.
- break;
-
-
- case kSetPowerLevel:
- // kGetPowerLevel and kSetPowerLevel are sent as a result of software (including
- // our very driver) calling SetDevicePowerLevel or GetDevicePowerLevel. It
- // is recommended that all power state changes come through here to allow the possibility
- // of improved power state monitoring by the Power Manager. For example, during handling
- // of the kSleepDemand message we might call:
- //
- // err = SetDevicePowerLevel (&gOurDeviceRegEntry, kPMDevicePowerLevel_Off);
- //
- // and handle the actual details in our kSetPowerLevel case statement.
- //
- // Note that, currently, these are the only selectors that can be called at any time and
- // not just during the sleep/wake process. Please see Power.h for the definition of the power
- // levels (kPMDevicePowerLevel_On, kPMDevicePowerLevel_D1, etc.).
- switch (*(PowerLevel *)ioParam)
- {
- case kPMDevicePowerLevel_Off:
- // turn things off
- break;
-
- case kPMDevicePowerLevel_On:
- // turn things on
- break;
- }
- err = noErr;
- break;
-
- case kGetPowerLevel:
- // determine current power level and return to caller, e.g.:
- *(PowerLevel *)ioParam = kPMDevicePowerLevel_On;
- err = noErr;
- break;
-
-
- case kGetPowerInfo:
- // The Power Mgr will call this before sleeping to determine if we support
- // removing power from our PCI device during sleep.
- {
- DevicePowerInfo * powerInfoPtr;
-
- powerInfoPtr = ( DevicePowerInfo * ) ioParam;
- if( SampleDriverSupportsPCIPowerOff() )
- {
- powerInfoPtr->flags |= kDevicePCIPowerOffAllowed;
- }
- else
- {
- // NOTE: You must clear this flag as it will be set by default.
-
- powerInfoPtr->flags &= ~kDevicePCIPowerOffAllowed;
- }
- err = noErr;
- }
- break;
-
-
- case kDeviceInitiatedWake:
- // The kDeviceInitiatedWake message is sent by the Power Mgr to see how
- // the machine was awakened. It may perform certain actions based on the result
- // returned, perhaps to support partial wakeup.
- if ( OurDeviceWokeMachine() )
- *(UInt32 *)ioParam = kDeviceRequestsFullWake;
- else
- *(UInt32 *)ioParam = kDeviceDidNotWakeMachine;
- err = noErr;
- break;
-
- default:
- break;
- }
-
- return( err );
- }
-
- /*==================================================================================================
- SampleDriverSupportsPCIPowerOff
- ==================================================================================================*/
-
- Boolean SampleDriverSupportsPCIPowerOff( void )
- {
- return( true );
- }
-
- /*==================================================================================================
- OurDeviceWokeMachine
- ==================================================================================================*/
-
- Boolean OurDeviceWokeMachine( void )
- {
- return( false );
- }
-
- /*==================================================================================================
- CanWeSleepDeviceNow
- ==================================================================================================*/
-
- OSStatus CanWeSleepDeviceNow( void )
- {
- OSStatus err = kPowerMgtRequestDenied;
-
- if ( true /* we can sleep device */ )
- err = noErr;
- return err;
- }
-
- /*==================================================================================================
- PutOurDeviceToSleep
- ==================================================================================================*/
-
- void PutOurDeviceToSleep( void )
- {
- OSStatus err;
- // take steps to save volatile memory and enter low power state
- err = SetDevicePowerLevel (&gOurDeviceRegEntry, kPMDevicePowerLevel_Off);
- }
-
- /*==================================================================================================
- WakeOurDevice
- ==================================================================================================*/
-
- void WakeOurDevice( void )
- {
- OSStatus err;
- // take steps to restore context and ready device for use
- err = SetDevicePowerLevel (&gOurDeviceRegEntry, kPMDevicePowerLevel_On);
- }